﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.Win32;
using BasePlatformCommon;

namespace L9SubSet
{
	public class Tools
	{
		#region 转换数据表

        static UInt32[] crcTable = {
 					0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B,
  0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
  0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7,
  0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
  0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3,
  0x709F7B7A, 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
  0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF,
  0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
  0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB,
  0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
  0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 0x34867077, 0x30476DC0,
  0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
  0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4,
  0x0808D07D, 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
  0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08,
  0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
  0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC,
  0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
  0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 0xE0B41DE7, 0xE4750050,
  0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
  0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34,
  0xDC3ABDED, 0xD8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
  0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1,
  0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
  0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5,
  0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
  0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 0xF12F560E, 0xF5EE4BB9,
  0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
  0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD,
  0xCDA1F604, 0xC960EBB3, 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
  0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71,
  0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
  0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2,
  0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
  0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E,
  0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
  0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A,
  0x2D15EBE3, 0x29D4F654, 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
  0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676,
  0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
  0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662,
  0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
  0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
                                   };

		private static byte[] bitSwapTable = 
			{
					0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
					0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
					0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
					0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
					0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
					0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
					0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
					0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
					0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
					0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
					0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
					0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
					0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
					0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
					0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
					0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
					0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
					0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
					0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
					0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
					0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
					0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
					0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
					0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
					0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
					0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
					0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
					0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
					0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
					0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
					0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
					0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
			};

		#endregion

		// byte[] 转 string
		public static string Byte2HexString(byte[] bytes)
		{
			StringBuilder sb = new StringBuilder();
			if (bytes != null)
			{
				for (int i = 0; i < bytes.Length; i++)
				{
					sb.Append(bytes[i].ToString("X2"));
				}
			}
			return sb.ToString() + "\n";
		}

		// byte[] 转 string
		public static string Byte2HexStringWith0x(byte[] bytes)
		{
			StringBuilder sb = new StringBuilder();
			if (bytes != null)
			{
				for (int i = 0; i < bytes.Length; i++)
				{
					sb.Append(bytes[i].ToString("X2"));
				}
			}
			return "0x" + sb.ToString();
		}

		// byte[] 转 string
		public static string Byte2HexString4RBF(byte[] bytes)
		{
			StringBuilder sb = new StringBuilder();
			if (bytes != null)
			{
				for (int i = 0; i < bytes.Length; i++)
				{
					if (i == 0)
					{
						sb.Append(i.ToString("X8").ToLower().PadLeft(8, '0') + "h: ");
					}
					else if (i > 0 && i % 16 == 0)
					{
						sb.Append("\n" + i.ToString("X8").ToLower().PadLeft(8, '0') + "h: ");
					}
					sb.Append(bytes[i].ToString("X2") + " ");
				}
			}
			return sb.ToString() + "\n";
		}

		// byte[] 转 string
		public static string Byte2HexString4Sub(byte[] bytes)
		{
			int[] addrArray = new int[] { 0x10100, 0x11000, 0x13000, 0x13100, 0x14000, 0x14100, 0x17000, 0x17100, 0x17200 };
			string splitLine = "---------------------------------------";
			StringBuilder sb = new StringBuilder();
			if (bytes != null && bytes.Length == 128 * 1024)
			{
				for (int addrIndex = 0; addrIndex < addrArray.Length; addrIndex++)
				{
					for (int i = addrArray[addrIndex]; i < addrArray[addrIndex] + 0x100; i++)
					{
						if (i == addrArray[addrIndex])
						{
							sb.Append(i.ToString("X8").ToLower().PadLeft(8, '0') + "h: ");
						}
						else if (i > 0 && i % 16 == 0)
						{
							sb.Append("\n" + i.ToString("X8").ToLower().PadLeft(8, '0') + "h: ");
						}
						sb.Append(bytes[i].ToString("X2") + " ");
					}
					
					if (addrIndex < addrArray.Length - 1)
					{
						sb.Append(splitLine + "\n");
					}
					else
					{
						sb.Append(splitLine);
					}
				}
			}
			return sb.ToString() + "\n";
		}

		// byte[] 转 string
		public static string Byte2HexString(byte[] bytes, int length)
		{
			string str = String.Empty;
			if (bytes != null)
			{
				for (int i = 0; i < length; i++)
				{
					str += bytes[i].ToString("X2");
				}
			}
			return str + "\n";
		}

		// byte[]转string
		public static string Byte2HexStringFriendly(byte[] bytes)
		{
			StringBuilder sb = new StringBuilder();
			if (bytes != null)
			{
				for (int i = 0; i < bytes.Length; i++)
				{
					if (i == 0)
					{
						sb.Append(i.ToString("X8").ToLower().PadLeft(8, '0') + "h: ");
					}
					else if (i > 0 && i % 16 == 0)
					{
						sb.Append("\n" + i.ToString("X8").ToLower().PadLeft(8, '0') + "h: ");
					}
					sb.Append(bytes[i].ToString("X2") + " ");
				}
			}
			return sb.ToString() + "\n";
		}

		// string 转 byte[]
		public static byte[] String2Bytes(string str)
		{
			return System.Text.Encoding.Default.GetBytes(str);
		}

		// 字符串转 16 进制字节数组 
		public static byte[] StringToHexByte(string hexString)
		{
			hexString = hexString.Replace(" ", "");
			if ((hexString.Length % 2) != 0)
			{
				hexString += " ";
			}
			
			byte[] returnBytes = new byte[hexString.Length / 2];
			for (int i = 0; i < returnBytes.Length; i++)
			{
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Trim(), 16);
			}

			return returnBytes;
		}

		// 创建 24 位位图
		public static Bitmap build24BitMap(int width, int height, byte[] view_data)
		{
			int headerLength = 54;
			int bfSize_v = width * height * 3 + headerLength;

			byte[] data = new byte[headerLength + view_data.Length];

			byte[] bfType = System.Text.Encoding.Default.GetBytes("BM");	// 图片类型
			byte[] bfSize = int2Byte4BigEnd(bfSize_v);		// 位图文件大小 - 字节为单位
			byte[] bfReserced = int2Byte4BigEnd(0);			// 保留 - 设置为0
			byte[] bfOffBits = int2Byte4BigEnd(54);			// 从文件头开始到实际图像数据之间的字节偏移量

			byte[] biSize = int2Byte4BigEnd(40);			// BMP文件头所需字节数
			byte[] biWidth = int2Byte4BigEnd(width);		// 图像宽度 - 像素为单位
			byte[] biHeight = int2Byte4BigEnd(height);		// 图像高度 - 像素为单位
			byte[] biPlanes = int2Byte2BigEnd(1);					// 颜色平面数, 总为1
			byte[] biBitCount = int2Byte2BigEnd(24);				// 像素位宽, 其值为1、4、8、16、24、32
			byte[] biCopression = int2Byte4BigEnd(0);		// 数据压缩类型：0-不压缩
			byte[] biSizeImage = int2Byte4BigEnd(0);		// 图像大小, 字节为单位, BI_RGB格式下可为0
			byte[] biXpelsPerMeter = int2Byte4BigEnd(0);	// 水平分辨率 像素/米
			byte[] biYpelsPerMeter = int2Byte4BigEnd(0);	// 垂直分辨率 像素/米
			byte[] biClrUsed = int2Byte4BigEnd(0);			// 位图实际使用的彩色表中的颜色索引数, 若为0说明使用所有的调色板项
			byte[] biClrImportant = int2Byte4BigEnd(0);		// 对图像显示有重要影响的颜色索引数目, 若为0说明都重要

			int index = 0;

			// 组装 bmp 文件头
			addByte(ref data, bfType, ref index);
			addByte(ref data, bfSize, ref index);
			addByte(ref data, bfReserced, ref index);
			addByte(ref data, bfOffBits, ref index);

			// 组装 bmp 信息头
			addByte(ref data, biSize, ref index);
			addByte(ref data, biWidth, ref index);
			addByte(ref data, biHeight, ref index);
			addByte(ref data, biPlanes, ref index);
			addByte(ref data, biBitCount, ref index);
			addByte(ref data, biCopression, ref index);
			addByte(ref data, biSizeImage, ref index);
			addByte(ref data, biXpelsPerMeter, ref index);
			addByte(ref data, biYpelsPerMeter, ref index);
			addByte(ref data, biClrUsed, ref index);
			addByte(ref data, biClrImportant, ref index);

			// 组装显示数据
			addByte(ref data, view_data, ref index);

			// 利用内存流生成图片
			MemoryStream ms = new MemoryStream(data);
			Bitmap bmp = (Bitmap)Bitmap.FromStream(ms);

			// 镜像操作
			bmp.RotateFlip(RotateFlipType.Rotate180FlipX);

			return bmp;
		}

		// byte[]拼接
		public static void addByte(ref byte[] oriBytes, byte[] newBytes, ref int index)
		{
			Array.Copy(newBytes, 0, oriBytes, index, newBytes.Length);
			index += newBytes.Length;
		}

		// byte[]拼接
		public static void addByte(ref byte[] oriBytes, byte newByte, ref int index)
		{
			byte[] b = new byte[1];
			b[0] = newByte;
			Array.Copy(b, 0, oriBytes, index, b.Length);
			index += b.Length;
		}

        // int 转 byte[2] - 低字节在前高字节在后
		public static byte[] int2Byte2BigEnd(int i)
		{
			byte[] b = new byte[2];
			b[0] = (byte)(0xff & i);
			b[1] = (byte)((0xff00 & i) >> 8);

			return b;
		}

        // int 转 byte[2] - 低字节在前高字节在后
        public static byte[] int2Byte2SmallEnd(int i) {
            byte[] b = new byte[2];
            b[0] = (byte)((0xff00 & i) >> 8);
            b[1] = (byte)(0xff & i);

            return b;
        }

		// int 转 byte[4] - 低字节在前高字节在后
		public static byte[] int2Byte4BigEnd(int i)
		{
			byte[] b = new byte[4];
			b[0] = (byte)(0xff & i);
			b[1] = (byte)((0xff00 & i) >> 8);
			b[2] = (byte)((0xff0000 & i) >> 16);
			b[3] = (byte)((0xff000000 & i) >> 24);

			return b;
		}

		// int 转 byte[4] - 高字节在前低字节在后
		public static byte[] int2Byte4SmallEnd(int i)
		{
			byte[] b = new byte[4];
			b[3] = (byte)(0xff & i);
			b[2] = (byte)((0xff00 & i) >> 8);
			b[1] = (byte)((0xff0000 & i) >> 16);
			b[0] = (byte)((0xff000000 & i) >> 24);

			return b;
		}

		// 计算 CRC32
		public static int getCRC32(byte[] bytes)
		{
			int iCount = bytes.Length;
			UInt32 crc = 0xFFFFFFFF;
			for (int i = 0; i < iCount; i++)
			{
				crc = ((crc >> 8) & 0x00FFFFFF) ^ crcTable[(crc ^ bytes[i]) & 0xFF];
			}
			UInt32 temp = crc ^ 0xFFFFFFFF;
			int t = (int)temp;
			return t;
		}

		// 计算 CRC32
		public static uint getCRC32Software(byte[] dataBuff, uint dataLength)
		{
            uint nReg = 0xFFFFFFFF; //
            for (int j = 0; j < dataBuff.Length; j++)
            {
                nReg ^= (UInt32)dataBuff[j];

                for (int i = 0; i < 4; i++)
                {
                    uint nTemp = crcTable[(byte)((nReg >> 24) & 0xff)]; //取一个字节，查表
                    nReg <<= 8; //丢掉计算过的头一个BYTE
                    nReg ^= nTemp; //与前一个BYTE的计算结果异或
                }
            }
            return nReg;
		}

		// 位转换 bit swap
		public static byte bitSwap(byte value)
		{
			return bitSwapTable[value];
		}

        // 位转换 bit swap
        public static byte bitSwap2(byte data) {
            data = (byte)((data << 4) | (data >> 4));
            data = (byte)(((data << 2) & 0xcc) | ((data >> 2) & 0x33));
            data = (byte)(((data << 1) & 0xaa) | ((data >> 1) & 0x55));
            return data;
        }

		// 比较字节数组
		public static int MemoryCompare(byte[] b1, byte[] b2)
		{
			if (b1 == null || b2 == null)
			{
				return 1;
			}

			int result = 0;
			if (b1.Length != b2.Length)
			{
				result = b1.Length - b2.Length;
			}
			else
			{
				for (int i = 0; i < b1.Length; i++)
				{
					if (b1[i] != b2[i])
					{
						result = (int)(b1[i] - b2[i]);
						break;
					}
				}
			}
			
			return result;
		}

        public static void ShowErrorMessage(IWin32Window owner, string msg) {
            var title = "错误";
            if (LanguageOper.available) {
                title = LanguageOper.ReadValue("Common", "errorStr");
            }
            MessageBoxEx.Show(owner, msg, title, MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        public static void ShowTipMessage(IWin32Window owner, string msg)
        {
            var title = "提示";
            if (LanguageOper.available)
            {
                title = LanguageOper.ReadValue("Common", "tipStr");
            }
            MessageBoxEx.Show(owner, msg, title, MessageBoxButtons.OK, MessageBoxIcon.None);
        }

        public static List<string> getColorOrderList() {
            var list = new List<string>();
            list.Add("RGB");
            list.Add("RBG");
            list.Add("BGR");
            list.Add("BRG");
            list.Add("GRB");
            list.Add("GBR");
            list.Add("RGBW");
            return list;
        }
	}

    public static class EnumHelper<T> {
        public static List<T> GetEnumMembers() {
            var list = new List<T>();
            foreach (T item in System.Enum.GetValues(typeof(T))) {
                list.Add(item);
            }
            return list;
        }
    }
}
